import 'package:word_game/engine/core.dart';

import 'attack_action.dart';
import 'role_action.dart';
import 'skills/skill.dart';
import 'skills/skill_action.dart';
import 'battleable.dart';
import 'monster.dart';

class BattleManager {
  static BattleManager instance = BattleManager();
  Future<bool> battle(Battleable hero, List<Monster> monsters) async {
    List<Battleable> stableHeros = [hero];
    List<Monster> stableMonsters = [];
    stableMonsters.addAll(monsters);
    int number = 1;
    while (stableHeros.length > 0 && stableMonsters.length > 0) {
      Engine.instance.displayer.displayString('第${number}回合：');

      List<Battleable> sequence =
          determineSequenceInRound(stableHeros, stableMonsters, number);

      for (var item in sequence) {
        if (item.vitality <= 0) {
          continue; // 已死亡
        }

        // 执行Buff的hot效果
        for (var buff in item.buffs) {
          if (buff.vitalityIncrement<=0) {
            continue;
          }
          int result = item.performHealAction(buff.vitalityIncrement);
          Engine.instance.displayer.displayString('${buff.name}生效，${item.name}恢复了${result}点生命，剩余血量${item.vitality}。');

          buff.effectRound++;
        }

        if (!item.canDoAction(number)) {
          Engine.instance.displayer.displayString('${item.name}被禁止攻击。');
        } else {
          List<Battleable> alternatives = [];
          List<Battleable> friends = [];
          if (item is Hero) {
            alternatives = stableMonsters;
            friends = stableHeros;
          } else {
            alternatives = stableHeros;
            friends = stableMonsters;
          }
          RoleAction action = item.determineAction(number);
          if (action is AttackAction) {
            List<Battleable> targets =
                item.determineNormalAttackTargets(alternatives);
            for (var target in targets) {
              AttackResult result = target.performAttackAction(action);
              Engine.instance.displayer.displayString(
                  '${item.name}攻击${target.name}：${target.name}${result.reason}，剩余血量${target.vitality}。');
            }
          } else if (action is SkillAction) {
            Skill skill = action.skill;
            Engine.instance.displayer
                .displayString('${item.name}使用了[${skill.name}]技能：');
            List<Monster> targets = skill.determineTargets(alternatives);
            AttackAction attack = skill.determineAction(item as Hero);
            for (var monster in targets) {
              AttackResult result = monster.performAttackAction(attack);
              Engine.instance.displayer.displayString(
                  '${monster.name}${result.reason}，剩余血量${monster.vitality}。');
              // 添加debuff到对手
              for (var debuff in skill.debuffs) {
                monster.debuffs.add(debuff.copy());
                Engine.instance.displayer
                    .displayString('${monster.name}获得Debuff效果：${debuff.name}。');
              }
            }
            // 添加buff到友方
            for (var buff in skill.buffs) {
              var targets = skill.determineBuffTargets(friends);
              for (var target in targets) {
                target.buffs.add(buff.copy());
                Engine.instance.displayer
                    .displayString('${target.name}获得Buff效果：${buff.name}。');
              }
            }
          }
          for (var item in alternatives.reversed.toList()) {
            if (item.vitality <= 0) {
              alternatives.remove(item);
            }
          }
        }

        // 执行Debuff的攻击动作
        for (var debuff in item.debuffs) {
          AttackAction action = debuff.action;
          if (action != null) {
            AttackResult result = item.performAttackAction(action);
            Engine.instance.displayer.displayString(
                '${debuff.name}生效，${item.name}${result.reason}，剩余血量${item.vitality}。');
          }

          debuff.effectRound++;
        }
        // 移除失效buff
        item.buffs.removeWhere((test) => test.effectRound >= test.lastRound);
        // 移除失效debuff
        item.debuffs.removeWhere((test) => test.effectRound >= test.lastRound);
      }

      number++;
    }
    if (stableHeros.length > 0) {
      return true;
    } else {
      return false;
    }
  }

  /// 确定攻击顺序
  List<Battleable> determineSequenceInRound(
      List<Battleable> heros, List<Battleable> monsters, int round) {
    List<Battleable> all = [];
    all.addAll(heros);
    all.addAll(monsters);
    all.sort((a, b) => a.attackPriority.compareTo(b.attackPriority));
    return all;
  }
}
